package com.china08.yxyapi.service.baijiayun.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.china08.yxyapi.entity.db.meeting.VideoMeeting;
import com.china08.yxyapi.entity.db.meeting.VideoMeetingInviteUser;
import com.china08.yxyapi.repository.db.VideoMeetingInviteUserRepository;
import com.china08.yxyapi.repository.db.VideoMeetingRepository;
import com.china08.yxyapi.repository.db.VideoMeetingUserRepository;
import com.china08.yxyapi.security.profile.YxyProfile;
import com.china08.yxyapi.service.baijiayun.MeetingRoomService;
import com.google.gson.Gson;

@Service
public class MeetingRoomServiceImpl implements MeetingRoomService {

    @Value(value = "${yx.rest.api.yx.path}")
    private String yxyApiYxUrl;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private VideoMeetingRepository videoMeetingRepository;

    @Autowired
    private VideoMeetingInviteUserRepository videoMeetingInviteUserRepository;// v1.1

    @Autowired
    private VideoMeetingUserRepository videoMeetingUserRepository;// v1.1

    /**
     * 创建房间
     * 
     * @param meetingId
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    @Override
    public void meetingRoomCrt(String meetingId) {
        VideoMeeting vmMeeting = videoMeetingRepository.findOne(meetingId);
        if (vmMeeting != null) {
            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/x-www-form-urlencoded;charset=UTF-8");// post-form
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE.toString());

            List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
            AssembleObject assemble = new AssembleObject();
            assemble.key = "partner_id";
            assemble.value = 37421489;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "title";
            assemble.value = vmMeeting.getTitle();
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "start_time";
            assemble.value = vmMeeting.getStartDate().getTime() / 1000;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "end_time";
            assemble.value = vmMeeting.getEndDate().getTime() / 1000;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "pre_enter_time";
            assemble.value = 1800;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "speak_camera_turnon";
            assemble.value = 2;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "timestamp";
            assemble.value = System.currentTimeMillis() / 1000;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "type";
            assemble.value = 2;
            sendList.add(assemble);

            // 参数排序
            sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

            // 追加签名
            assemble = new AssembleObject();
            assemble.key = "sign";
            assemble.value = getSign(sendList);
            sendList.add(assemble);

            // 拼接参数
            StringBuffer sendBuffer = new StringBuffer();
            for (AssembleObject assembleObject : sendList) {
                sendBuffer.append(assembleObject.toString());
            }
            String sendStr = sendBuffer.toString().substring(1);

            HttpEntity<String> formEntity = new HttpEntity<String>(sendStr, headers);
            String httpResult = restTemplate.postForObject("https://api.baijiayun.com/openapi/room/create", formEntity,
                    String.class);
            Gson gson = new Gson();
            Map<String, Map<String, Object>> resultMap = gson.fromJson(httpResult, Map.class);
            if (Double.parseDouble(resultMap.get("code") + "") == 0) {
                // 数据保存
                vmMeeting.setRoomId(resultMap.get("data").get("room_id").toString());
                vmMeeting.setAdminCode(resultMap.get("data").get("admin_code").toString());
                vmMeeting.setTeacherCode(resultMap.get("data").get("teacher_code").toString());
                vmMeeting.setStudentCode(resultMap.get("data").get("student_code").toString());
                videoMeetingRepository.save(vmMeeting);
            } else {
                videoMeetingRepository.delete(vmMeeting.getId());
                Assert.isTrue(false, resultMap.get("msg") + "");
            }
        }
    }

    /**
     * 获取视频连接地址
     * 
     * @param meetingId
     * @param userId
     * @return
     */
    @Override
    public String getMeetingRoomUrl(String meetingId, YxyProfile user) {

        List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        AssembleObject assemble = new AssembleObject();

        VideoMeeting vmMeeting = videoMeetingRepository.findByIdAndSpeakerId(meetingId, user.getId());
        if (vmMeeting != null) {
            assemble = new AssembleObject();
            assemble.key = "user_role";
            assemble.value = 1;
            sendList.add(assemble);
        } else {
            vmMeeting = videoMeetingRepository.findOne(meetingId);
            if (vmMeeting != null) {
                if (!vmMeeting.getSchoolId().equals(user.getSchoolId())) {//
                    return null;
                }
                assemble = new AssembleObject();
                assemble.key = "user_role";
                assemble.value = 0;
                sendList.add(assemble);
            } else {
                Assert.isTrue(false, "会议视频直播地址不存在");
                return null;
            }
        }
        assemble = new AssembleObject();
        assemble.key = "room_id";
        assemble.value = vmMeeting.getRoomId();
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_number";
        assemble.value = System.currentTimeMillis() / 1000;
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_name";
        assemble.value = user.getUserNick();
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_avatar";
        assemble.value = user.getUserAvator();
        sendList.add(assemble);

        // 参数排序
        sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

        // 追加签名
        assemble = new AssembleObject();
        assemble.key = "sign";
        assemble.value = getSign(sendList);
        sendList.add(assemble);

        // 拼接参数
        StringBuffer sendBuffer = new StringBuffer();
        for (AssembleObject assembleObject : sendList) {
            sendBuffer.append(assembleObject.toString());
        }
        String sendStr = sendBuffer.toString().substring(1);

        return "http://www.baijiayun.com/web/room/enter?" + sendStr;
    }

    /**
     * 获取视频连接地址 v1.1
     * 
     * @param meetingId
     * @param userId
     * @return
     */
    @Override
    public String getMeetingRoomUrlV1_1(String meetingId, YxyProfile user) {

        List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        AssembleObject assemble = new AssembleObject();

        VideoMeeting vmMeeting = videoMeetingRepository.findByIdAndSpeakerIdAndSchoolId(meetingId, user.getId(),
                user.getSchoolId()); // v1.1
        if (vmMeeting != null) { // 为主讲人
            assemble = new AssembleObject();
            assemble.key = "user_role";
            assemble.value = 1;
            sendList.add(assemble);
        } else {
            vmMeeting = videoMeetingRepository.findOne(meetingId);
            if (vmMeeting != null) { // v1.1
                // 判断选定人员列表里是否存在
                List<String> userIds = new ArrayList<String>();
                userIds.add(user.getId());
                userIds.add(user.getSchoolId());
                userIds.add(user.getSchoolAreaIdDistrict());
                userIds.add(user.getSchoolAreaIdCity());

                Integer userCount = videoMeetingUserRepository.countByMeetingIdAndUserIdIn(meetingId, userIds);
                if (userCount < 0) { // 没有在邀请列表里存在
                    return null;
                }

                if (user.getRoleId().equals("ROLE_TEACHER")) { // 角色为老师
                    VideoMeetingInviteUser inviteUser = videoMeetingInviteUserRepository
                            .findByMeetingIdAndSchoolIdAndUserId(meetingId, user.getSchoolId(), user.getId());
                    if (inviteUser == null) { // 是否在特邀列表
                        return null;
                    }
                }
                assemble = new AssembleObject();
                assemble.key = "user_role";
                assemble.value = 0;
                sendList.add(assemble);
            } else {
                Assert.isTrue(false, "会议视频直播地址不存在");
                return null;
            }
        }

        if (vmMeeting.getStatus() != 0 && vmMeeting.getStatus() != 1) {
            Assert.isTrue(false, "会议视频直播已结束或已取消");
            return null;
        }

        int baijiayunId = 0;// v1.1
        try {
            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE.toString());
            Map<String, Object> formMap = new HashMap<String, Object>();
            formMap.put("userId", user.getId());
            HttpEntity<Map<String, Object>> formEntity = new HttpEntity<Map<String, Object>>(formMap, headers);
            BaijiayunUser httpResult = restTemplate.postForObject(yxyApiYxUrl + "/comm/baijiayun/getextid", formEntity,
                    BaijiayunUser.class);

            baijiayunId = httpResult.id;
            if (baijiayunId == 0) {
                Assert.isTrue(false, "获取百家云用户id失败");
            }
        } catch (RestClientException e) {
            // TODO Auto-generated catch block
            Assert.isTrue(false, "获取百家云用户id失败");
        }

        assemble = new AssembleObject();
        assemble.key = "room_id";
        assemble.value = vmMeeting.getRoomId();
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_number";
        assemble.value = baijiayunId;// v1.1
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_name";
        assemble.value = user.getUserNick();
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "user_avatar";
        assemble.value = user.getUserAvator();
        sendList.add(assemble);

        // 参数排序
        sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

        // 追加签名
        assemble = new AssembleObject();
        assemble.key = "sign";
        assemble.value = getSign(sendList);
        sendList.add(assemble);

        // 拼接参数
        StringBuffer sendBuffer = new StringBuffer();
        for (AssembleObject assembleObject : sendList) {
            sendBuffer.append(assembleObject.toString());
        }
        String sendStr = sendBuffer.toString().substring(1);

        return "http://www.baijiayun.com/web/room/enter?" + sendStr;
    }

    protected static class BaijiayunUser {
        public int id;
    }

    /**
     * 获取视频连接地址(根据邀请码)
     * 
     * @param meetingId
     * @param code
     * @param userNick
     * @return
     */
    @Override
    public String getMeetingRoomUrlByCodeV1_1(String meetingId, String code) {

        VideoMeeting vmMeeting = videoMeetingRepository.findOne(meetingId);
        if (vmMeeting != null) {
            if (!code.equals(vmMeeting.getStudentCode()) //
                    && !code.equals(vmMeeting.getTeacherCode()) //
                    && !code.equals(vmMeeting.getAdminCode())) {//
                Assert.isTrue(false, "会议视频直播邀请码不正确");
                return null;
            }
            StringBuffer url = new StringBuffer();
            // 自定义输入昵称
            url.append("http://www.baijiayun.com/web/room/prepare?room_id=");
            url.append(vmMeeting.getRoomId());
            url.append("&code=");
            url.append(code);
            // url.append("&urlType=12345abcde");

            // 手动输入昵称
            // url.append("http://www.baijiayun.com/web/room/quickenter?code=");
            // url.append(code);
            // url.append("&user_name=");
            // url.append(userNick);

            return url.toString();
        } else {
            Assert.isTrue(false, "会议视频直播地址不存在");
            return null;
        }
    }

    /**
     * 获取视频连接地址(根据邀请码)
     * 
     * @param meetingId
     * @param code
     * @param userNick
     * @return
     */
    @Override
    public String getMeetingRoomUrlByCode(String meetingId, String code, String userNick) {

        VideoMeeting vmMeeting = videoMeetingRepository.findOne(meetingId);
        if (vmMeeting != null) {
            if (!code.equals(vmMeeting.getStudentCode()) //
                    && !code.equals(vmMeeting.getTeacherCode()) //
                    && !code.equals(vmMeeting.getAdminCode())) {//
                Assert.isTrue(false, "会议视频直播邀请码不正确");
                return null;
            }

            if (vmMeeting.getStatus() != 0 && vmMeeting.getStatus() != 1) {
                Assert.isTrue(false, "会议视频直播已结束或已取消");
                return null;
            }

            StringBuffer url = new StringBuffer();
            // 自定义输入昵称
            // url.append("http://www.baijiayun.com/web/room/prepare?room_id=");
            // url.append(vmMeeting.getRoomId());
            // url.append("&code=");
            // url.append(code);
            // url.append("&urlType=12345abcde");

            // 手动输入昵称
            url.append("http://www.baijiayun.com/web/room/quickenter?code=");
            url.append(code);
            url.append("&user_name=");
            url.append(userNick);

            return url.toString();
        } else {
            Assert.isTrue(false, "会议视频直播地址不存在");
            return null;
        }
    }

    /**
     * 删除房间
     * 
     * @param meetingId
     */
    @Override
    public void meetingRoomDel(String meetingId) {
        VideoMeeting vmMeeting = videoMeetingRepository.findOne(meetingId);
        if (vmMeeting != null) {
            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/x-www-form-urlencoded;charset=UTF-8");// post-form
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE.toString());

            List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
            AssembleObject assemble = new AssembleObject();
            assemble.key = "partner_id";
            assemble.value = 37421489;
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "room_id";
            assemble.value = vmMeeting.getRoomId();
            sendList.add(assemble);

            assemble = new AssembleObject();
            assemble.key = "timestamp";
            assemble.value = System.currentTimeMillis() / 1000;
            sendList.add(assemble);

            // 参数排序
            sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

            // 追加签名
            assemble = new AssembleObject();
            assemble.key = "sign";
            assemble.value = getSign(sendList);
            sendList.add(assemble);

            // 拼接参数
            StringBuffer sendBuffer = new StringBuffer();
            for (AssembleObject assembleObject : sendList) {
                sendBuffer.append(assembleObject.toString());
            }
            String sendStr = sendBuffer.toString().substring(1);

            HttpEntity<String> formEntity = new HttpEntity<String>(sendStr, headers);
            String httpResult = restTemplate.postForObject("https://api.baijiayun.com/openapi/room/delete", formEntity,
                    String.class);
            Gson gson = new Gson();
            Map<String, Map<String, Object>> resultMap = gson.fromJson(httpResult, Map.class);
            if (Double.parseDouble(resultMap.get("code") + "") == 0) {
                // 数据保存
                vmMeeting.setRoomId("");
                vmMeeting.setAdminCode("");
                vmMeeting.setTeacherCode("");
                vmMeeting.setStudentCode("");
                videoMeetingRepository.save(vmMeeting);
            } else {
                Assert.isTrue(false, resultMap.get("msg") + "");
            }
        }
    }

    /**
     * 获取教师是否在直播间
     * 
     * @param vmMeeting
     * @return 1-在直播间 0-不在直播间 2-异常
     */
    @Override
    public Integer onlineStatus(VideoMeeting vmMeeting) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/x-www-form-urlencoded;charset=UTF-8");// post-form
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE.toString());

        List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        AssembleObject assemble = new AssembleObject();
        assemble.key = "partner_id";
        assemble.value = 37421489;
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "room_id";
        assemble.value = vmMeeting.getRoomId();
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "timestamp";
        assemble.value = System.currentTimeMillis() / 1000;
        sendList.add(assemble);

        // 参数排序
        sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

        // 追加签名
        assemble = new AssembleObject();
        assemble.key = "sign";
        assemble.value = getSign(sendList);
        sendList.add(assemble);

        // 拼接参数
        StringBuffer sendBuffer = new StringBuffer();
        for (AssembleObject assembleObject : sendList) {
            sendBuffer.append(assembleObject.toString());
        }
        String sendStr = sendBuffer.toString().substring(1);

        HttpEntity<String> formEntity = new HttpEntity<String>(sendStr, headers);
        String httpResult = restTemplate.postForObject("https://api.baijiayun.com/openapi/live/getTeacherOnlineStatus",
                formEntity, String.class);
        Gson gson = new Gson();
        Map<String, Map<String, Object>> resultMap = gson.fromJson(httpResult, Map.class);
        if (Double.parseDouble(resultMap.get("code") + "") == 0) {
            if (Double.parseDouble(resultMap.get("data").get("status") + "") == 1) { //
                return 1;
            } else {
                return 0;
            }
        } else {
            return 2;
        }
    }

    /**
     * 获取直播间观看记录
     * 
     * @param roomId
     * @return
     */
    @Override
    public Integer getRoomReport(String roomId) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/x-www-form-urlencoded;charset=UTF-8");// post-form
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE.toString());

        List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        AssembleObject assemble = new AssembleObject();
        assemble.key = "partner_id";
        assemble.value = 37421489;
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "room_id";
        assemble.value = roomId;
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "type";
        assemble.value = "all";
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "timestamp";
        assemble.value = System.currentTimeMillis() / 1000;
        sendList.add(assemble);

        // 参数排序
        sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));

        // 追加签名
        assemble = new AssembleObject();
        assemble.key = "sign";
        assemble.value = getSign(sendList);
        sendList.add(assemble);

        // 拼接参数
        StringBuffer sendBuffer = new StringBuffer();
        for (AssembleObject assembleObject : sendList) {
            sendBuffer.append(assembleObject.toString());
        }
        String sendStr = sendBuffer.toString().substring(1);

        HttpEntity<String> formEntity = new HttpEntity<String>(sendStr, headers);
        String httpResult = restTemplate.postForObject("https://api.baijiayun.com/openapi/room_data/exportLiveReport",
                formEntity, String.class);
        Gson gson = new Gson();
        Map<String, Map<String, Object>> resultMap = gson.fromJson(httpResult, Map.class);
        if (Double.parseDouble(resultMap.get("code") + "") == 0) {
            Integer count = Integer.valueOf((int) Double.parseDouble(resultMap.get("data").get("total") + ""));
            return count;
        } else {
            return null;
        }
    }

    /**
     * 生成签名
     * 
     * @param list
     * @return
     */
    public String getSign(List<AssembleObject> list) {
        List<AssembleObject> signLst = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        signLst.addAll(list);
        AssembleObject assemble = new AssembleObject();
        assemble.key = "partner_key";
        assemble.value = getPartner_key();
        signLst.add(assemble);
        StringBuffer signBuffer = new StringBuffer();
        for (AssembleObject assembleObject : signLst) {
            signBuffer.append(assembleObject.toString());
        }
        return DigestUtils.md5Hex(signBuffer.toString().substring(1));
    }

    /**
     * 获取partner_key
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    public String getPartner_key() {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/x-www-form-urlencoded;charset=UTF-8");// post-form
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE.toString());

        List<AssembleObject> sendList = new ArrayList<MeetingRoomServiceImpl.AssembleObject>();
        AssembleObject assemble = new AssembleObject();
        assemble.key = "partner_id";
        assemble.value = "37421489";
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "secret_key";
        assemble.value = "5b630039880be2853fb58e5c9520f3ad";
        sendList.add(assemble);

        assemble = new AssembleObject();
        assemble.key = "regenerate";// 是否重新生成partner_key 0-不生成，1强制生成
        assemble.value = 0;
        sendList.add(assemble);
        // 参数排序
        sendList.sort((AssembleObject a1, AssembleObject a2) -> a1.key.compareTo(a2.key));
        StringBuffer sendBuffer = new StringBuffer();
        for (AssembleObject assembleObject : sendList) {
            sendBuffer.append(assembleObject.toString());
        }
        String sendStr = sendBuffer.toString().substring(1);
        HttpEntity<String> formEntity = new HttpEntity<String>(sendStr, headers);
        String httpResult = restTemplate.postForObject("https://api.baijiayun.com/openapi/partner/createkey",
                formEntity, String.class);
        Gson gson = new Gson();
        Map<String, Map<String, Object>> resultMap = gson.fromJson(httpResult, Map.class);
        if (Double.parseDouble(resultMap.get("code") + "") == 0) {
            return resultMap.get("data").get("partner_key").toString();
        } else {
            Assert.isTrue(false, resultMap.get("msg") + "");
        }
        return null;
    }

    // 组装对象
    protected static class AssembleObject {
        String key;
        Object value;

        @Override
        public String toString() {
            return "&" + key + "=" + value;
        }
    }
}
